updating oE cmd_parse

cmd_parse

include cmdline.e 
namespace cmdline 
public function cmd_parse(sequence opts, object parse_options = {}, 
        sequence cmds = command_line()) 

parses command line options and optionally calls procedures based on these options.

Parameters:
  1. opts : a sequence of records that define the various command line switches and options that are valid for the application: See Comments: section for details
  2. parse_options : an optional list of special behavior modifiers: See Parse Options section for details
  3. cmds : an optional sequence of command line arguments. If omitted the output from command_line is used.
Returns:

A map, containing the set of actual options used in cmds. The returned map has one special key, EXTRAS that are values passed on the command line that are not part of any of the defined options. This is commonly used to get the list of files entered on the command line. For instance, if the command line used was myprog -verbose file1.txt file2.txt then the EXTRAS data value would be {"file1.txt", "file2.txt"}.

When any command item begins with an @ symbol then it is assumed that it prefixes a file name. That file will then be opened and its contents used to add to the command line, as if the file contents had actually been entered as part of the original command line.

Parse Options: parse_options is used to provide a set of behavior modifiers that change the default rules for parsing the command line. If used, it is a list of values that will affect the parsing of the command line options.

These modifers can be any combination of:

  1. VALIDATE_ALL -- The default. All options will be validated for all possible errors.
  2. NO_VALIDATION -- Do not validate any parameter.
  3. NO_VALIDATION_AFTER_FIRST_EXTRA -- Do not validate any parameter after the first extra was encountered. This is helpful for programs such as the Interpreter itself: eui -D TEST greet.ex -name John. -D TEST should be validated but anything after "greet.ex" should not as it is meant for greet.ex to handle, not eui.
  4. HELP_RID -- The next Parse Option must either a routine id or a set of text strings. The routine is called or the text is displayed when a parse error (invalid option given, mandatory option not given, no parameter given for an option that requires a parameter, etc...) occurs. This can be used to provide additional help text. By default, just the option switches and their descriptions will be displayed. However you can provide additional text by either supplying a routine_id of a procedure that accepts no parameters, or a sequence containing lines of text (one line per element). The procedure is expected to write text to the stdout device.
  5. NO_HELP_ON_ERROR -- Do not show a list of options on a command line error.
  6. NO_HELP -- Do not automatically add the switches '-h', '-?', and '--help' to display the help text (if any).
  7. NO_AT_EXPANSION -- Do not expand arguments that begin with '@.'
  8. AT_EXPANSION -- Expand arguments that begin with '@'. The name that follows @ will be opened as a file, read, and each trimmed non-empty line that does not begin with a '#' character will be inserted as arguments in the command line. These lines replace the original '@' argument as if they had been entered on the original command line.
    • If the name following the '@' begins with another '@', the extra '@' is removed and the remainder is the name of the file. However, if that file cannot be read, it is simply ignored. This allows optional files to be included on the command line. Normally, with just a single '@', if the file cannot be found the program aborts.
    • Lines whose first non-whitespace character is '#' are treated as a comment and thus ignored.
    • Lines enclosed with double quotes will have the quotes stripped off and the result is used as an argument. This can be used for arguments that begin with a '#' character, for example.
    • Lines enclosed with single quotes will have the quotes stripped off and the line is then further split up use the space character as a delimiter. The resulting 'words' are then all treated as individual arguments on the command line.

An example of parse options:

{ HELP_RID, routine_id("my_help"), NO_VALIDATION } 
Comments:

Token types recognized on the command line:

  1. a single '-'. Simply added to the 'extras' list
  2. a single "--". This signals the end of command line options. What remains of the command line is added to the 'extras' list, and the parsing terminates.
  3. -shortName. The option will be looked up in the short name field of opts.
  4. /shortName. Same as -shortName.
  5. -!shortName. If the 'shortName' has already been found the option is removed.
  6. /!shortName. Same as -!shortName
  7. --longName. The option will be looked up in the long name field of opts.
  8. --!longName. If the 'longName' has already been found the option is removed.
  9. anything else. The word is simply added to the 'extras' list.

For those options that require a parameter to also be supplied, the parameter can be given as either the next command line argument, or by appending '=' or ':' to the command option then appending the parameter data.
For example, -path=/usr/local or as -path /usr/local.

On a failed lookup, the program shows the help by calling show_help(opts, add_help_rid, cmds) and terminates with status code 1.

If you do not explicitly define the switches -h, -?, or --help, these will be automatically added to the list of valid switches and will be set to call the show_help routine.

You can remove any of these as default 'help' switches simply by explicitly using them for something else.

You can also remove all of these switches as automatic help switches by using the NO_HELP parsing option. This just means that these switches are not automatically used as 'help' switches, regardless of whether they are used explicitly or not. So if NO_HELP is used, and you want to give the user the ability to display the 'help' then you must explicitly set up your own switch to do so. N.B, the 'help' is still displayed if an invalid command line switch is used at runtime, regardless of whether NO_HELP is used or not.

Option records have the following structure:

  1. a sequence representing the (short name) text that will follow the "-" option format. Use an atom if not relevant
  2. a sequence representing the (long name) text that will follow the "--" option format. Use an atom if not relevant
  3. a sequence, text that describes the option's purpose. Usually short as it is displayed when "-h"/"--help" is on the command line. Use an atom if not required.
  4. An object ...
    • If an atom then it can be either HAS_PARAMETER or anything else if there is no parameter for this option. This format also implies that the option is optional, case-sensitive and can only occur once.
    • If a sequence, it can containing zero or more processing flags in any order ...
      • MANDATORY to indicate that the option must always be supplied.
      • HAS_PARAMETER to indicate that the option must have a parameter following it. You can optionally have a name for the parameter immediately follow the HAS_PARAMETER flag. If one isn't there, the help text will show "x" otherwise it shows the supplied name.
      • NO_CASE to indicate that the case of the supplied option is not significant.
      • ONCE to indicate that the option must only occur once on the command line.
      • MULTIPLE to indicate that the option can occur any number of times on the command line.
    • If both ONCE and MULTIPLE are omitted then switches that also have HAS_PARAMETER are only allowed once but switches without HAS_PARAMETER can have multuple occurances but only one is recorded in the output map.
  5. an integer; a routine_id. This function will be called when the option is located on the command line and before it updates the map.
    Use -1 if cmd_parse is not to invoke a function for this option.
    The user defined function must accept a single sequence parameter containing four values. If the function returns 1 then the command option does not update the map. You can use the predefined index values OPT_IDX, OPT_CNT, OPT_VAL, OPT_REV when referencing the function's parameter elements.
    1. An index into the opts list.
    2. The number of times that the routine has been called by cmd_parse for this option
    3. The option's value as found on the command line
    4. 1 if the command line indicates that this option is to remove any earlier occurrences of it.

One special circumstance exists and that is an option group header. It should contain only two elements:

  1. The header constant: HEADER
  2. A sequence to display as the option group header

When assigning a value to the resulting map, the key is the long name if present, otherwise it uses the short name. For options, you must supply a short name, a long name or both.

If you want cmd_parse to call a user routine for the extra command line values, you need to specify an Option Record that has neither a short name or a long name, in which case only the routine_id field is used.

For more details on how the command line is being pre-parsed, see command_line.

Example 1:
   -- simple usage 
 
map args = cmd_parse({   
    { "o", 0, "Output directory", { HAS_PARAMETER } },   
    { "v", 0, "Verbose mode" }   
}) 
 
if map:get(args, "v") then 
    printf(1, "Output directory is %s\n", { map:get(args, "o") }) 
end if 
Example 2:
    -- complex usage 
 
sequence option_definition 
integer gVerbose = 0 
sequence gOutFile = {} 
sequence gInFile = {} 
function opt_verbose( sequence value) 
   if value[OPT_VAL] = -1 then -- (-!v used on command line) 
   	gVerbose = 0 
   else 
     if value[OPT_CNT] = 1 then 
        gVerbose = 1 
     else 
        gVerbose += 1 
     end if 
   end if 
	return 1 
end function 
 
function opt_output_filename( sequence value) 
   gOutFile = value[OPT_VAL] 
	return 1 
end function 
 
function extras( sequence value) 
   if not file_exists(value[OPT_VAL]) then 
       show_help(option_definition, sprintf("Cannot find '%s'",  
                 {value[OPT_VAL]}) ) 
       abort(1) 
   end if 
   gInFile = append(gInFile, value[OPT_VAL]) 
	return 1 
end function 
 
option_definition = { 
    { HEADER,         "General options" }, 
    { "h", "hash",    "Calc hash values", { NO_PARAMETER }, -1 }, 
    { HEADER,         "Input and output" }, 
    { "o", "output",  "Output filename",  { MANDATORY, HAS_PARAMETER, ONCE } ,  
                                            routine_id("opt_output_filename") }, 
    { "i", "import",  "An import path",   { HAS_PARAMETER, MULTIPLE}, -1 }, 
    { HEADER,         "Miscellaneous" }, 
    { "v", "verbose", "Verbose output",   { NO_PARAMETER }, routine_id("opt_verbose") }, 
    { "e", "version", "Display version",  { VERSIONING, "myprog v1.0" } }, 
    {  0, 0, 0, 0, routine_id("extras")} 
} 
 
map:map opts = cmd_parse(option_definition, NO_HELP) 
 
-- When run as:  
--             eui myprog.ex -v @output.txt -i /etc/app input1.txt input2.txt 
-- and the file "output.txt" contains the two lines ... 
--   --output=john.txt 
--   '-i /usr/local' 
-- 
-- map:get(opts, "verbose") --> 1 
-- map:get(opts, "hash") --> 0 (not supplied on command line) 
-- map:get(opts, "output") --> "john.txt" 
-- map:get(opts, "import") --> {"/usr/local", "/etc/app"} 
-- map:get(opts, EXTRAS) --> {"input1.txt", "input2.txt"} 
See Also:

show_help, command_line

Not Categorized, Please Help

Search



Quick Links

User menu

Not signed in.

Misc Menu